QW
📷 换头像
我的订单
全部 >
QW电竞护航平台 · v6.0
🏷️
0 红钻
商品名称
店铺:未知
商品描述
库存:0
🏪
店铺名称
店铺简介
⭐ 4.9
📦 0 商品
👥 0 关注
// ============================================================
// 第4部分:完整前端 JavaScript 代码
// 包含:配置、工具函数、导航、子页面管理、广告、商城、分类、帖子、订单、消息、充值、用户管理、店铺管理、客服、派单、分类管理、广告管理、图标管理、认证、初始化
// ============================================================
// ============================================================
// 配置
// ============================================================
const API_URL = '/api';
let currentUser = null;
let token = localStorage.getItem('token');
let announceImages = [];
let userFilter = 'all';
let currentCategoryFilter = 'all';
let currentSubCategoryFilter = 'all';
let currentContactId = null;
let currentChatType = 'contact';
let currentOrderId = null;
let currentSubPage = null;
let currentShopId = null;
let currentShopProducts = [];
let currentShopFilter = 'all';
let bannerImages = [];
let bannerIndex = 0;
let bannerTimer = null;
let allShops = [];
let shopCategories = [];
let allProducts = [];
let currentProductId = null;
let fullscreenContactId = null;
let fullscreenChatType = 'contact';
let fullscreenOrderId = null;
let allPosts = [];
let currentPostPage = 1;
const POSTS_PER_PAGE = 20;
let myOrderFilter = 'all';
let userFilterSub = 'all';
let categorySubFilter = 'all';
// ============================================================
// 工具函数
// ============================================================
function toast(msg, type) {
const t = document.getElementById('toast');
t.textContent = msg;
t.className = 'toast show' + (type === 'error' ? ' error' : type === 'warning' ? ' warning' : '');
clearTimeout(t._timer);
t._timer = setTimeout(() => t.classList.remove('show'), 3000);
}
function statusText(s) {
const map = { 'pending': '待接单', 'ongoing': '进行中', 'review': '待验收', 'completed': '已完成', 'canceled': '已取消', 'rejected': '已驳回', 'refund_pending': '退款申请中', 'refunded': '已退款', 'settled': '已结算' };
return map[s] || s;
}
function statusClass(s) {
if (s === 'hidden') return 'status-hidden';
if (s === 'refund_pending') return 'status-refund_pending';
if (s === 'refunded') return 'status-refunded';
if (s === 'settled') return 'status-settled';
return 'status-' + s;
}
async function apiRequest(url, options = {}) {
const headers = { 'Content-Type': 'application/json' };
if (token) {
headers['Authorization'] = token;
}
if (options.headers) {
Object.assign(headers, options.headers);
}
try {
const res = await fetch(API_URL + url, { ...options, headers });
if (!res.ok) {
let errMsg = `请求失败 (${res.status})`;
try {
const err = await res.json();
errMsg = err.error || errMsg;
} catch (e) {}
throw new Error(errMsg);
}
return await res.json();
} catch (err) {
console.error('API请求失败:', url, err);
throw err;
}
}
function showCustomModal(html) {
document.getElementById('customModalContent').innerHTML = html;
document.getElementById('customModal').classList.add('active');
}
function closeCustomModal() {
document.getElementById('customModal').classList.remove('active');
}
function showImgPreview(src) {
const modal = document.getElementById('imgPreviewModal');
if (!modal) {
const overlay = document.createElement('div');
overlay.className = 'modal-overlay active';
overlay.id = 'imgPreviewModal';
overlay.innerHTML = `
`;
document.body.appendChild(overlay);
overlay.classList.add('active');
return;
}
document.getElementById('imgPreviewSrc').src = src;
modal.classList.add('active');
}
function closeImgPreview() {
const modal = document.getElementById('imgPreviewModal');
if (modal) modal.classList.remove('active');
}
function confirmAction(title, message, confirmText, callback) {
showCustomModal(`
${title}
${message}
`);
}
function updateHeaderDiamond() {
if (!currentUser) {
document.getElementById('headerDiamond').textContent = '0';
document.getElementById('headerUnreadMail').textContent = '0';
return;
}
document.getElementById('headerDiamond').textContent = currentUser.diamond || 0;
apiRequest('/mails').then(mails => {
const unread = mails.filter(m => m.status === 'unread').length;
document.getElementById('headerUnreadMail').textContent = unread;
}).catch(() => {});
}
function formatTime(timeStr) {
if (!timeStr) return '';
const date = new Date(timeStr);
const now = new Date();
const diff = Math.floor((now - date) / 1000);
if (diff < 60) return '刚刚';
if (diff < 3600) return Math.floor(diff / 60) + '分钟前';
if (diff < 86400) return Math.floor(diff / 3600) + '小时前';
if (diff < 604800) return Math.floor(diff / 86400) + '天前';
return date.toLocaleDateString();
}
// ============================================================
// 获取支持联系人
// ============================================================
async function getSupportContacts() {
try {
const contacts = await apiRequest('/support-contacts');
return contacts || [];
} catch (err) {
console.warn('获取支持联系人失败:', err);
return [];
}
}
// ============================================================
// 弹窗公告系统
// ============================================================
let announceData = null;
async function loadAnnounceData() {
try {
const data = await fetch(API_URL + '/announce').then(r => r.json());
announceData = data;
return data;
} catch (err) {
console.error('加载公告失败', err);
return null;
}
}
function showAnnounceModal() {
if (!announceData) return;
const dontShow = localStorage.getItem('announce_dont_show');
if (dontShow === 'true') return;
const content = announceData.content || '欢迎使用 QW电竞护航平台!';
if (content.trim() === '' || content === '欢迎使用 QW电竞护航平台!') return;
document.getElementById('announceModalTitle').textContent = '📢 公告';
document.getElementById('announceModalContent').textContent = content;
const imagesContainer = document.getElementById('announceModalImages');
imagesContainer.innerHTML = '';
if (announceData.images && announceData.images.length > 0) {
announceData.images.forEach(img => {
const imgEl = document.createElement('img');
imgEl.src = img;
imgEl.onclick = function() { showImgPreview(img); };
imagesContainer.appendChild(imgEl);
});
}
document.getElementById('announceModal').classList.add('active');
}
function closeAnnounceModal() {
const checkbox = document.getElementById('announceDontShow');
if (checkbox.checked) {
localStorage.setItem('announce_dont_show', 'true');
}
document.getElementById('announceModal').classList.remove('active');
}
// ============================================================
// 底部导航
// ============================================================
function renderBottomNav() {
const nav = document.getElementById('bottomNav');
if (!nav) return;
let items = [
{ id: 'home', icon: 'fa-store', label: '商城' },
{ id: 'category', icon: 'fa-th-large', label: '分类' },
{ id: 'posts', icon: 'fa-newspaper', label: '帖子' },
{ id: 'messages', icon: 'fa-comment-dots', label: '消息', badge: 'msgBadge' },
{ id: 'account', icon: 'fa-user', label: '我的' }
];
nav.innerHTML = items.map(item => `
`).join('');
nav.removeEventListener('click', handleNavClick);
nav.addEventListener('click', handleNavClick);
}
function handleNavClick(e) {
const btn = e.target.closest('.nav-item');
if (!btn) return;
const target = btn.dataset.target;
if (!target) return;
e.preventDefault();
navigateTo(target);
}
function navigateTo(target) {
closeSubPage();
closeShopDetail();
closeProductDetail();
closeChatFullscreen();
document.querySelectorAll('.bottom-nav .nav-item').forEach(n => {
n.classList.toggle('active', n.dataset.target === target);
});
document.querySelectorAll('.view').forEach(v => v.classList.remove('active'));
const viewMap = {
'home': 'view-home',
'category': 'view-category',
'posts': 'view-posts',
'messages': 'view-messages',
'account': 'view-account'
};
const viewId = viewMap[target];
if (viewId) {
const viewEl = document.getElementById(viewId);
if (viewEl) {
viewEl.classList.add('active');
switch(target) {
case 'home': renderHomePage(); startBannerAuto(); break;
case 'category': renderCategoryPage(); break;
case 'posts': renderPosts(); break;
case 'messages': loadContacts(); break;
case 'account': renderMyPage(); break;
default: break;
}
}
}
}
// ============================================================
// 子页面管理
// ============================================================
function openSubPage(page) {
const pageMap = {
'orders': 'subPageOrders',
'products': 'subPageProducts',
'users': 'subPageUsers',
'recharges': 'subPageRecharges',
'shops': 'subPageShops',
'announce': 'subPageAnnounce',
'withdrawals': 'subPageWithdrawals',
'account': 'subPageAccount',
'service': 'subPageService',
'dispatcher': 'subPageDispatcher',
'categories': 'subPageCategories',
'banners': 'subPageBanners',
'icons': 'subPageIcons'
};
const containerId = pageMap[page];
if (!containerId) return;
currentSubPage = page;
document.getElementById(containerId).classList.add('active');
document.body.style.overflow = 'hidden';
switch(page) {
case 'orders': renderSubOrders(); break;
case 'products': renderSubProducts(); break;
case 'users': renderSubUsers(); break;
case 'recharges': renderSubRecharges(); break;
case 'shops': renderSubShops(); break;
case 'announce': renderSubAnnounce(); break;
case 'withdrawals': renderSubWithdrawals(); break;
case 'account': renderSubAccount(); break;
case 'service': renderSubService(); break;
case 'dispatcher': renderSubDispatcher(); break;
case 'categories': renderSubCategories(); break;
case 'banners': renderSubBanners(); break;
case 'icons': renderSubIcons(); break;
}
}
function closeSubPage() {
document.querySelectorAll('.sub-page').forEach(el => el.classList.remove('active'));
document.body.style.overflow = '';
currentSubPage = null;
}
// ============================================================
// 店铺详情(修复 - 可进入店铺)
// ============================================================
function openShopDetail(shopId) {
currentShopId = shopId;
apiRequest('/shops/' + shopId).then(shop => {
document.getElementById('sdTitle').textContent = shop.name || '店铺详情';
document.getElementById('sdName').textContent = shop.name || '未知店铺';
document.getElementById('sdDesc').textContent = shop.description || '暂无简介';
document.getElementById('sdRating').textContent = shop.rating || '4.9';
document.getElementById('sdProducts').textContent = shop.productCount || 0;
document.getElementById('sdFollows').textContent = shop.follow_count || 0;
const bannerEl = document.getElementById('sdBanner');
if (shop.banner) {
bannerEl.innerHTML = `
`;
} else if (shop.logo) {
bannerEl.innerHTML = `
`;
} else {
bannerEl.textContent = '🏪';
}
document.getElementById('shopDetailModal').classList.add('active');
document.body.style.overflow = 'hidden';
// 加载店铺商品
apiRequest('/shops/' + shopId + '/products').then(products => {
const container = document.getElementById('sdProductList');
if (products.length === 0) {
container.innerHTML = '';
return;
}
let html = '📦 店铺商品
';
products.forEach(p => {
const remaining = p.quantity - p.sold;
html += `
${p.image ? `

` : '🏷️'}
${p.game || '商品'}
${p.title}
${p.description || ''}
剩余 ${remaining}
${p.price} 红钻
`;
});
html += '
';
container.innerHTML = html;
}).catch(err => {
document.getElementById('sdProductList').innerHTML = '';
});
}).catch(err => {
toast('加载店铺失败: ' + err.message, 'error');
});
}
function closeShopDetail() {
document.getElementById('shopDetailModal').classList.remove('active');
document.body.style.overflow = '';
currentShopId = null;
}
// ============================================================
// 广告轮播
// ============================================================
function initBanner() {
loadBannerFromStorage();
renderBanner();
startBannerAuto();
}
function loadBannerFromStorage() {
try {
const saved = localStorage.getItem('banner_images');
if (saved) {
bannerImages = JSON.parse(saved);
}
} catch (e) { bannerImages = []; }
}
function saveBannerToStorage() {
try {
localStorage.setItem('banner_images', JSON.stringify(bannerImages));
} catch (e) {}
}
function renderBanner() {
const track = document.getElementById('bannerTrack');
const dots = document.getElementById('bannerDots');
if (!track || !dots) return;
if (bannerImages.length === 0) {
track.innerHTML = `📢 暂无广告
`;
dots.innerHTML = '';
return;
}
track.innerHTML = bannerImages.map(img => `
`).join('');
dots.innerHTML = bannerImages.map((_, i) => `
`).join('');
track.style.transform = `translateX(-${bannerIndex * 100}%)`;
}
function goToBanner(index) {
if (index < 0) index = bannerImages.length - 1;
if (index >= bannerImages.length) index = 0;
bannerIndex = index;
renderBanner();
}
function nextBanner() {
if (bannerImages.length === 0) return;
goToBanner(bannerIndex + 1);
}
function prevBanner() {
if (bannerImages.length === 0) return;
goToBanner(bannerIndex - 1);
}
function startBannerAuto() {
if (bannerTimer) clearInterval(bannerTimer);
if (bannerImages.length > 1) {
bannerTimer = setInterval(nextBanner, 4000);
}
}
function stopBannerAuto() {
if (bannerTimer) {
clearInterval(bannerTimer);
bannerTimer = null;
}
}
async function loadBannersFromAPI() {
try {
const banners = await apiRequest('/banners');
bannerImages = banners.map(b => b.image_url).filter(url => url);
saveBannerToStorage();
renderBanner();
} catch (err) {
console.error('加载广告失败:', err);
}
}
// ============================================================
// 商城首页
// ============================================================
async function renderHomePage() {
try {
const shops = await apiRequest('/shops') || [];
allShops = shops;
renderShopEntrance(shops);
const products = await apiRequest('/products') || [];
allProducts = products;
renderHomeProducts(products);
await loadBannersFromAPI();
initBanner();
} catch (err) {
console.error(err);
}
}
function renderShopEntrance(shops) {
const container = document.getElementById('shopEntrance');
if (!container) return;
if (shops.length === 0) {
container.innerHTML = '暂无店铺
';
return;
}
container.innerHTML = shops.slice(0, 10).map(s => `
${s.logo ? `

` : '🏪'}
${s.name}
`).join('');
}
function renderHomeProducts(products) {
const container = document.getElementById('homeProductList');
if (!container) return;
if (products.length === 0) {
container.innerHTML = '';
return;
}
let html = '';
products.forEach(p => {
const remaining = p.quantity - p.sold;
html += `
${p.image ? `

` : '🏷️'}
${p.category_name || p.game || '商品'}
${p.title}
${p.description || ''}
剩余 ${remaining}
${p.price} 红钻
${remaining > 0 ? (currentUser ? `
` : ``) : '已售罄'}
${p.shop_name || ''}
`;
});
html += '
';
container.innerHTML = html;
}
// ============================================================
// 分类页面
// ============================================================
let categoryProducts = [];
async function renderCategoryPage() {
try {
const categories = await apiRequest('/categories') || [];
const mainCats = categories.filter(c => !c.parent_id);
const container = document.getElementById('categoryButtons2');
if (container) {
container.innerHTML = '';
mainCats.forEach(c => {
const btn = document.createElement('button');
btn.className = 'category-btn';
btn.dataset.category = c.id;
btn.textContent = c.image ? c.image + ' ' + c.name : c.name;
btn.onclick = function() { filterProductsByCategory(c.id); };
container.appendChild(btn);
});
}
const products = await apiRequest('/products') || [];
categoryProducts = products;
renderCategoryProducts('all');
} catch (err) {
console.error(err);
}
}
function filterProductsByCategory(categoryId) {
currentCategoryFilter = categoryId;
document.querySelectorAll('#categoryNavWrapper2 .category-btn').forEach(b => b.classList.remove('active'));
const targetBtn = document.querySelector(`#categoryNavWrapper2 .category-btn[data-category="${categoryId}"]`);
if (targetBtn) targetBtn.classList.add('active');
if (categoryId === 'all') {
document.querySelector('#categoryNavWrapper2 .category-btn[data-category="all"]')?.classList.add('active');
}
renderCategoryProducts(categoryId);
}
function filterSubCategory2(subCategory) {
categorySubFilter = subCategory;
document.querySelectorAll('#subCategoryWrapper2 .sub-btn').forEach(b => b.classList.remove('active'));
const targetBtn = document.querySelector(`#subCategoryWrapper2 .sub-btn[data-sub="${subCategory}"]`);
if (targetBtn) targetBtn.classList.add('active');
renderCategoryProducts(currentCategoryFilter);
}
function renderCategoryProducts(categoryId) {
const container = document.getElementById('categoryProductList');
if (!container) return;
let products = categoryProducts;
if (categoryId !== 'all') {
products = products.filter(p => p.category_id === categoryId);
}
if (categorySubFilter !== 'all') {
products = products.filter(p => p.category_id === categorySubFilter);
}
if (products.length === 0) {
container.innerHTML = '';
return;
}
let html = '';
products.forEach(p => {
const remaining = p.quantity - p.sold;
html += `
${p.image ? `

` : '🏷️'}
${p.category_name || p.game || '商品'}
${p.title}
${p.description || ''}
剩余 ${remaining}
${p.price} 红钻
${remaining > 0 ? (currentUser ? `
` : ``) : '已售罄'}
${p.shop_name || ''}
`;
});
html += '
';
container.innerHTML = html;
}
// ============================================================
// 商品详情
// ============================================================
async function openProductDetail(productId) {
currentProductId = productId;
try {
const product = await apiRequest('/products/' + productId);
document.getElementById('pdTitle').textContent = product.title || '商品详情';
document.getElementById('pdPrice').textContent = (product.price || 0) + ' 红钻';
document.getElementById('pdName').textContent = product.title || '';
document.getElementById('pdShop').textContent = '店铺:' + (product.shop_name || '未知');
document.getElementById('pdDesc').textContent = product.detail_desc || product.description || '暂无描述';
document.getElementById('pdStock').textContent = '库存:' + (product.quantity - (product.sold || 0));
const imgContainer = document.getElementById('pdImage');
if (product.image) {
imgContainer.innerHTML = `
`;
} else {
imgContainer.textContent = '🏷️';
}
document.getElementById('productDetailModal').classList.add('active');
document.body.style.overflow = 'hidden';
} catch (err) {
toast(err.message, 'error');
}
}
function closeProductDetail() {
document.getElementById('productDetailModal').classList.remove('active');
document.body.style.overflow = '';
currentProductId = null;
}
function buyFromDetail() {
if (currentProductId) {
showBuyWithHandler(currentProductId);
}
}
// ============================================================
// 购买功能
// ============================================================
async function showBuyWithHandler(productId) {
if (!currentUser) { toast('请先登录', 'warning'); return; }
try {
const handlers = await apiRequest('/handlers');
let options = '';
handlers.forEach(h => {
options += ``;
});
showCustomModal(`
选择打手
可选择指定打手接单,或留空让打手自行接单
`);
document.getElementById('customModal').classList.add('active');
} catch (err) {
toast(err.message, 'error');
}
}
async function doBuyWithHandler(productId) {
const handlerId = document.getElementById('buyHandlerSelect').value;
closeCustomModal();
try {
const data = await apiRequest('/orders/buy', {
method: 'POST',
body: JSON.stringify({ productId, assignedHandlerId: handlerId || null })
});
toast('购买成功!订单号:' + data.orderId, 'success');
renderHomePage();
renderCategoryPage();
renderMyPage();
updateHeaderDiamond();
updateBadges();
} catch (err) {
toast(err.message, 'error');
}
}
// ============================================================
// 帖子系统
// ============================================================
async function renderPosts() {
const container = document.getElementById('postList');
if (!container) return;
try {
const posts = await apiRequest('/posts');
allPosts = posts;
document.getElementById('postCount').textContent = posts.length + '个';
if (posts.length === 0) {
container.innerHTML = '';
return;
}
let html = '';
for (const post of posts) {
const avatarUrl = post.avatar || '';
const images = post.images ? JSON.parse(post.images) : [];
const isLiked = post.is_liked || false;
const isOwner = currentUser && post.user_id === currentUser.id;
let imagesHtml = '';
if (images.length > 0) {
const gridClass = images.length === 1 ? '' : images.length === 2 ? 'grid-2' : 'grid-3';
imagesHtml = `${images.map(img => `

`).join('')}
`;
}
html += `
${post.content}
${imagesHtml}
`;
}
container.innerHTML = html;
} catch (err) {
console.error('加载帖子失败:', err);
container.innerHTML = '加载失败: ' + err.message + '
';
}
}
function refreshPosts() {
renderPosts();
toast('已刷新', 'success');
}
function showCreatePost() {
if (!currentUser) { toast('请先登录', 'warning'); return; }
showCustomModal(`
发布帖子
`);
document.getElementById('customModal').classList.add('active');
}
async function submitPost() {
const content = document.getElementById('postContent').value.trim();
const imagesInput = document.getElementById('postImages').value.trim();
const images = imagesInput ? imagesInput.split(',').map(s => s.trim()).filter(s => s) : [];
if (!content) { toast('请输入内容', 'warning'); return; }
try {
await apiRequest('/posts', {
method: 'POST',
body: JSON.stringify({ content, images })
});
closeCustomModal();
toast('✅ 帖子发布成功', 'success');
renderPosts();
renderMyPage();
} catch (err) {
toast(err.message, 'error');
}
}
async function likePost(postId) {
if (!currentUser) { toast('请先登录', 'warning'); return; }
try {
const result = await apiRequest('/posts/' + postId + '/like', { method: 'POST' });
const countEl = document.getElementById('like-count-' + postId);
if (countEl) {
const currentCount = parseInt(countEl.textContent) || 0;
countEl.textContent = result.liked ? currentCount + 1 : currentCount - 1;
}
const btn = document.querySelector(`#post-${postId} .post-actions button:first-child`);
if (btn) btn.classList.toggle('liked');
} catch (err) {
toast(err.message, 'error');
}
}
function toggleComments(postId) {
const container = document.getElementById('comments-' + postId);
if (container) {
const isHidden = container.style.display === 'none' || !container.style.display;
container.style.display = isHidden ? 'block' : 'none';
if (isHidden) {
loadComments(postId);
}
}
}
async function loadComments(postId) {
const container = document.getElementById('comments-list-' + postId);
if (!container) return;
try {
const post = await apiRequest('/posts/' + postId);
const comments = post.comments || [];
if (comments.length === 0) {
container.innerHTML = '暂无评论
';
return;
}
container.innerHTML = comments.map(c => `
`).join('');
} catch (err) {
console.error('加载评论失败:', err);
container.innerHTML = '加载失败
';
}
}
async function submitComment(postId) {
if (!currentUser) { toast('请先登录', 'warning'); return; }
const input = document.getElementById('comment-input-' + postId);
const content = input.value.trim();
if (!content) { toast('请输入评论内容', 'warning'); return; }
try {
await apiRequest('/posts/' + postId + '/comment', {
method: 'POST',
body: JSON.stringify({ content })
});
input.value = '';
toast('评论成功', 'success');
loadComments(postId);
const countEl = document.getElementById('comment-count-' + postId);
if (countEl) {
countEl.textContent = parseInt(countEl.textContent) + 1;
}
renderMyPage();
} catch (err) {
toast(err.message, 'error');
}
}
async function deletePost(postId) {
if (!currentUser) return;
confirmAction('确认删除', '确定要删除此帖子吗?', '删除', `doDeletePost('${postId}')`);
}
async function doDeletePost(postId) {
try {
await apiRequest('/posts/' + postId, { method: 'DELETE' });
toast('已删除', 'success');
renderPosts();
renderMyPage();
} catch (err) {
toast(err.message, 'error');
}
}
// ============================================================
// 头像上传
// ============================================================
function uploadAvatar() {
if (!currentUser) { toast('请先登录', 'warning'); return; }
showCustomModal(`
上传头像
输入图片URL设置头像
`);
document.getElementById('avatarUrlInput').addEventListener('input', function() {
const img = document.getElementById('avatarPreview');
if (this.value) {
img.src = this.value;
img.style.display = 'block';
img.onerror = function() { this.style.display = 'none'; };
} else {
img.style.display = 'none';
}
});
document.getElementById('customModal').classList.add('active');
}
async function doUploadAvatar() {
const url = document.getElementById('avatarUrlInput').value.trim();
if (!url) { toast('请输入图片URL', 'warning'); return; }
try {
await apiRequest('/user/avatar', {
method: 'POST',
body: JSON.stringify({ avatar_url: url })
});
closeCustomModal();
toast('✅ 头像已更新', 'success');
currentUser.avatar = url;
renderMyPage();
updateBadges();
} catch (err) {
toast(err.message, 'error');
}
}
// ============================================================
// "我的"页面
// ============================================================
async function renderMyPage() {
if (!currentUser) {
document.getElementById('profileName').textContent = '未登录';
document.getElementById('profileId').textContent = '用户ID:登录后查看';
document.getElementById('profileBalance').textContent = '0.00';
document.getElementById('profilePosts').textContent = '0';
document.getElementById('profileCoupons').textContent = '0';
document.getElementById('myBalance').textContent = '0.00';
document.getElementById('profileAvatarText').textContent = '?';
renderMoreFunctions();
return;
}
try {
const user = await apiRequest('/me');
const orders = await apiRequest('/orders/my') || [];
const posts = await apiRequest('/posts?user_id=' + currentUser.id) || [];
document.getElementById('profileName').innerHTML = user.username + ` LV${user.level || 1}`;
document.getElementById('profileId').textContent = '用户ID:' + (user.id || '--');
const balance = (user.diamond || 0) / 10;
document.getElementById('profileBalance').textContent = balance.toFixed(2);
document.getElementById('profilePosts').textContent = posts.length;
document.getElementById('profileCoupons').textContent = '0';
document.getElementById('myBalance').textContent = balance.toFixed(2);
const avatarText = user.username ? user.username.substring(0, 2).toUpperCase() : 'QW';
document.getElementById('profileAvatarText').textContent = avatarText;
if (user.avatar) {
document.getElementById('profileAvatarImg').src = user.avatar;
document.getElementById('profileAvatarImg').style.display = 'block';
document.getElementById('profileAvatarText').style.display = 'none';
} else {
document.getElementById('profileAvatarImg').style.display = 'none';
document.getElementById('profileAvatarText').style.display = 'block';
}
if (user.banner) {
document.getElementById('profileBannerImg').src = user.banner;
document.getElementById('profileBannerImg').style.display = 'block';
}
renderMyOrders(orders);
renderMoreFunctions();
} catch (err) {
console.error(err);
}
}
function filterMyOrders(filter) {
myOrderFilter = filter;
document.querySelectorAll('#orderTabs .tab-btn').forEach(b => b.classList.remove('active'));
const targetBtn = document.querySelector(`#orderTabs .tab-btn[data-status="${filter}"]`);
if (targetBtn) targetBtn.classList.add('active');
apiRequest('/orders/my').then(orders => {
renderMyOrders(orders);
}).catch(err => console.error(err));
}
function renderMyOrders(orders) {
const container = document.getElementById('myOrderList');
if (!container) return;
let filtered = orders;
if (myOrderFilter === 'pending') {
filtered = orders.filter(o => o.status === 'pending');
} else if (myOrderFilter === 'ongoing') {
filtered = orders.filter(o => o.status === 'ongoing' || o.status === 'review');
} else if (myOrderFilter === 'completed') {
filtered = orders.filter(o => o.status === 'completed');
} else if (myOrderFilter === 'refund') {
filtered = orders.filter(o => o.status === 'refund_pending' || o.status === 'refunded' || o.status === 'rejected');
}
if (filtered.length === 0) {
container.innerHTML = '';
return;
}
let html = '';
filtered.slice(0, 5).forEach(o => {
const statusMap = { 'pending': '待接单', 'ongoing': '进行中', 'review': '待验收', 'completed': '已完成', 'canceled': '已取消', 'rejected': '已驳回', 'refund_pending': '退款中', 'refunded': '已退款' };
html += `
${o.title}
${statusMap[o.status] || o.status}
`;
});
container.innerHTML = html;
}
function renderMoreFunctions() {
const container = document.getElementById('moreFunctions');
if (!container) return;
const role = currentUser?.role;
let items = [];
if (role === 'admin') {
items = [
{ icon: 'fa-clipboard-list', label: '订单管理', action: "openSubPage('orders')" },
{ icon: 'fa-boxes', label: '商品管理', action: "openSubPage('products')" },
{ icon: 'fa-users', label: '用户管理', action: "openSubPage('users')" },
{ icon: 'fa-coins', label: '充值管理', action: "openSubPage('recharges')" },
{ icon: 'fa-store', label: '店铺管理', action: "openSubPage('shops')" },
{ icon: 'fa-bullhorn', label: '公告管理', action: "openSubPage('announce')" },
{ icon: 'fa-money-bill', label: '提现管理', action: "openSubPage('withdrawals')" },
{ icon: 'fa-tags', label: '分类管理', action: "openSubPage('categories')" },
{ icon: 'fa-image', label: '广告管理', action: "openSubPage('banners')" },
{ icon: 'fa-palette', label: '图标管理', action: "openSubPage('icons')" },
{ icon: 'fa-paper-plane', label: '发布订单', action: "openSubPage('dispatcher')" },
{ icon: 'fa-cog', label: '账户设置', action: "openSubPage('account')" }
];
} else if (role === 'service') {
items = [
{ icon: 'fa-headset', label: '客服系统', action: "openSubPage('service')" },
{ icon: 'fa-coins', label: '充值审核', action: "openSubPage('recharges')" },
{ icon: 'fa-users', label: '用户管理', action: "openSubPage('users')" },
{ icon: 'fa-cog', label: '账户设置', action: "openSubPage('account')" }
];
} else if (role === 'dispatcher') {
items = [
{ icon: 'fa-clipboard-list', label: '派单系统', action: "openSubPage('dispatcher')" },
{ icon: 'fa-boxes', label: '商品管理', action: "openSubPage('products')" },
{ icon: 'fa-chart-bar', label: '数据统计', action: "openSubPage('orders')" },
{ icon: 'fa-cog', label: '账户设置', action: "openSubPage('account')" }
];
} else if (role === 'handler') {
items = [
{ icon: 'fa-gamepad', label: '打手工作台', action: "openSubPage('orders')" },
{ icon: 'fa-money-bill', label: '提现', action: "requestWithdraw()" },
{ icon: 'fa-cog', label: '账户设置', action: "openSubPage('account')" }
];
} else {
items = [
{ icon: 'fa-clipboard-list', label: '我的订单', action: "openSubPage('orders')" },
{ icon: 'fa-cog', label: '账户设置', action: "openSubPage('account')" }
];
}
container.innerHTML = items.map(item => `
${item.label}
`).join('');
}
function handleProfileClick() {
if (!currentUser) {
showLoginModal();
} else {
openSubPage('account');
}
}
// ============================================================
// 订单/打手页面
// ============================================================
async function renderOrdersPage() {
const role = currentUser?.role;
const title = document.getElementById('orderPageTitle');
const handlerInfo = document.getElementById('handlerInfo');
if (role === 'handler') {
title.textContent = '🎮 打手工作台';
handlerInfo.style.display = 'block';
await updateHandlerInfo();
} else {
title.textContent = '📋 我的订单';
handlerInfo.style.display = 'none';
}
await renderOrders();
}
async function updateHandlerInfo() {
try {
const user = await apiRequest('/me');
const balance = user.diamond || 0;
const frozen = Math.min(100, balance);
document.getElementById('handlerBalance').textContent = balance;
document.getElementById('handlerFrozen').textContent = frozen;
} catch (err) { console.error(err); }
}
async function renderOrders() {
try {
const orders = await apiRequest('/orders/my');
const container = document.getElementById('orderList');
if (!container) return;
document.getElementById('orderCount').textContent = orders.length + '个';
if (orders.length === 0) {
container.innerHTML = '';
return;
}
let html = '';
const role = currentUser?.role;
for (const o of orders) {
let actions = '';
let shouldShow = false;
if (role === 'admin' || role === 'service') {
shouldShow = true;
} else if (role === 'handler') {
shouldShow = (o.status === 'pending' || o.handler_id === currentUser.id);
} else if (role === 'boss') {
shouldShow = (o.boss_id === currentUser.id);
} else {
shouldShow = (o.boss_id === currentUser.id || o.handler_id === currentUser.id);
}
if (!shouldShow) continue;
if (o.status === 'pending' && role === 'handler') {
actions += ``;
}
if (o.status === 'ongoing' && role === 'handler' && o.handler_id === currentUser.id) {
actions += ``;
}
if (o.status === 'review' && (role === 'boss' || role === 'service')) {
actions += ``;
}
if ((o.status === 'ongoing' || o.status === 'pending') && (role === 'boss' || role === 'service')) {
actions += ``;
}
actions += ``;
actions += ``;
html += `
${o.game || '暗区突围'} · ${o.title}
${o.price} 红钻 | ${statusText(o.status)}
${actions}
`;
}
container.innerHTML = html || '';
} catch (err) {
console.error(err);
document.getElementById('orderList').innerHTML = '';
}
}
// ============================================================
// 订单操作函数
// ============================================================
window.confirmTake = function(orderId) {
confirmAction('确认接单', '确认接取此订单?(需保留100红钻冻结)', '确认接单', `doTake('${orderId}')`);
};
async function doTake(orderId) {
try {
await apiRequest('/orders/' + orderId + '/take', { method: 'PUT' });
toast('接单成功', 'success');
renderOrders();
renderMyPage();
updateHeaderDiamond();
updateBadges();
} catch (err) { toast(err.message, 'error'); }
}
window.confirmSubmitComplete = function(orderId) {
confirmAction('提交完成', '确认已完成此订单服务?', '确认提交', `doSubmitComplete('${orderId}')`);
};
async function doSubmitComplete(orderId) {
try {
await apiRequest('/orders/' + orderId + '/submit-complete', { method: 'PUT' });
toast('已提交验收', 'success');
renderOrders();
renderMyPage();
} catch (err) { toast(err.message, 'error'); }
}
window.confirmBossComplete = function(orderId) {
confirmAction('确认完成', '确认已完成此订单服务?', '确认完成', `doBossComplete('${orderId}')`);
};
async function doBossComplete(orderId) {
try {
await apiRequest('/orders/' + orderId + '/boss-confirm', { method: 'PUT' });
toast('已确认完成,等待管理员结算', 'success');
renderOrders();
renderMyPage();
updateBadges();
} catch (err) { toast(err.message, 'error'); }
}
window.requestRefund = function(orderId) {
showCustomModal(`
申请退款
请填写退款原因:
`);
};
async function doRequestRefund(orderId) {
const reason = document.getElementById('refundReasonInput').value.trim();
if (!reason) return toast('请填写退款原因', 'warning');
closeCustomModal();
try {
await apiRequest('/orders/' + orderId + '/refund-request', { method: 'PUT', body: JSON.stringify({ reason }) });
toast('退款申请已提交', 'success');
renderOrders();
renderMyPage();
} catch (err) { toast(err.message, 'error'); }
}
window.viewOrderDetail = function(orderId) {
apiRequest('/orders/' + orderId).then(order => {
let messages = [];
try {
if (typeof order.messages === 'string') messages = JSON.parse(order.messages);
else if (Array.isArray(order.messages)) messages = order.messages;
} catch (e) { messages = []; }
const messagesHtml = messages.length > 0 ?
messages.map(msg => `${msg.sender}: ${msg.content} ${msg.time}
`).join('') :
'暂无消息';
showCustomModal(`
订单详情
订单号${order.id}
游戏${order.game}
标题${order.title}
价格${order.price} 红钻
状态${statusText(order.status)}
打手${order.handler_id || '未指派'}
创建时间${order.created_at}
${order.start_time ? `
开始时间${order.start_time}
` : ''}
${order.end_time ? `
结束时间${order.end_time}
` : ''}
${order.settled ? `
结算金额${order.settled_amount||order.price} 红钻
` : ''}
${order.refund_reason ? `
退款原因${order.refund_reason}
` : ''}
`);
}).catch(err => toast(err.message, 'error'));
};
window.requestWithdraw = function() {
if (!currentUser) { toast('请先登录', 'warning'); return; }
const amount = parseInt(prompt('请输入要提现的红钻数量(需保留100冻结):'));
if (!amount || amount < 1) return toast('请输入有效数量', 'warning');
if (currentUser.role !== 'handler') return toast('只有打手可提现', 'warning');
const available = Math.max(0, (currentUser.diamond || 0) - 100);
if (amount > available) return toast(`可提现红钻不足,可用:${available} 红钻(需保留100冻结)`, 'error');
confirmAction('确认提现', `确认申请提现 ${amount} 红钻?`, '确认申请', `doRequestWithdraw(${amount})`);
};
async function doRequestWithdraw(amount) {
try {
const result = await apiRequest('/withdraw/request', {
method: 'POST',
body: JSON.stringify({ amount })
});
toast(result.message || '提现申请已提交', 'success');
renderOrders();
renderMyPage();
updateHeaderDiamond();
} catch (err) { toast(err.message, 'error'); }
}
// ============================================================
// 子页面 - 订单管理
// ============================================================
async function renderSubOrders() {
const container = document.getElementById('subOrdersContent');
if (!container) return;
try {
const orders = await apiRequest('/orders/my');
if (orders.length === 0) {
container.innerHTML = '';
return;
}
let html = '';
for (const o of orders) {
let actions = '';
if (o.status === 'review' && (currentUser.role === 'boss' || currentUser.role === 'service')) {
actions += ``;
}
if ((o.status === 'ongoing' || o.status === 'pending') && (currentUser.role === 'boss' || currentUser.role === 'service')) {
actions += ``;
}
if (o.status === 'pending' && currentUser.role === 'handler') {
actions += ``;
}
if (o.status === 'ongoing' && currentUser.role === 'handler') {
actions += ``;
}
actions += ``;
actions += ``;
html += `
${o.game || '暗区突围'} · ${o.title}
${o.price} 红钻 | ${statusText(o.status)}
${actions}
`;
}
container.innerHTML = html;
} catch (err) {
console.error(err);
container.innerHTML = '加载失败: ' + err.message + '
';
}
}
// ============================================================
// 子页面 - 商品管理
// ============================================================
async function renderSubProducts() {
const container = document.getElementById('subProductsContent');
if (!container) return;
try {
const products = await apiRequest('/admin/products');
let html = `
`;
container.innerHTML = html;
await renderProductsList();
await loadCategoriesForSelectors();
await loadShopSelect();
await loadShopCategorySelect();
} catch (err) {
console.error(err);
container.innerHTML = '加载失败: ' + err.message + '
';
}
}
function toggleInlineModal(id) {
const el = document.getElementById(id + 'Modal');
if (el) el.classList.toggle('active');
}
async function loadShopSelect() {
try {
const shops = await apiRequest('/shops') || [];
const sel = document.getElementById('prodShop');
if (!sel) return;
sel.innerHTML = '';
shops.forEach(s => {
sel.innerHTML += ``;
});
} catch (err) { console.error(err); }
}
async function loadShopCategorySelect() {
const shopId = document.getElementById('prodShop')?.value;
if (!shopId) return;
try {
const categories = await apiRequest('/shops/' + shopId + '/categories') || [];
const sel = document.getElementById('prodShopCategory');
if (!sel) return;
sel.innerHTML = '';
categories.forEach(c => {
sel.innerHTML += ``;
});
} catch (err) { console.error(err); }
}
async function loadShopCategoriesForProduct() {
await loadShopCategorySelect();
}
async function renderProductsList() {
try {
const products = await apiRequest('/admin/products');
const container = document.getElementById('productsList');
if (!container) return;
if (products.length === 0) {
container.innerHTML = '';
return;
}
let html = '| 标题 | 价格 | 库存 | 店铺 | 状态 | 操作 |
';
for (const p of products) {
const remaining = p.quantity - p.sold;
const isHidden = p.hidden == 1 || p.hidden === true;
let statusText2 = isHidden ? '已下架' : (remaining > 0 ? '在售' : '已售罄');
let statusCls = isHidden ? 'status-hidden' : (remaining > 0 ? 'status-onsale' : 'status-soldout');
const productId = p.id;
let actions = '';
if (isHidden) {
actions += ``;
actions += ``;
} else {
actions += ``;
}
actions += ``;
html += `
| ${p.title} |
${p.price} 红钻 |
${p.sold}/${p.quantity} |
${p.shop_name || '未分配'} |
${statusText2} |
${actions} |
`;
}
html += '
';
container.innerHTML = html;
} catch (err) { console.error(err); }
}
async function loadCategoriesForSelectors() {
try {
const categories = await apiRequest('/categories');
const mainCats = categories.filter(c => !c.parent_id);
const sel = document.getElementById('prodCategory');
if (!sel) return;
sel.innerHTML = '';
mainCats.forEach(c => {
sel.innerHTML += ``;
});
} catch (err) { console.error(err); }
}
async function shelfProduct() {
const category_id = document.getElementById('prodCategory').value || null;
const shop_id = document.getElementById('prodShop').value || null;
const shop_category_id = document.getElementById('prodShopCategory').value || null;
const title = document.getElementById('prodTitle').value.trim();
const desc = document.getElementById('prodDesc').value.trim();
const price = parseFloat(document.getElementById('prodPrice').value);
const quantity = parseInt(document.getElementById('prodQuantity').value) || 1;
const image = document.getElementById('prodImageUrl').value.trim();
const detail_images_raw = document.getElementById('prodDetailImages').value.trim();
const detail_desc = document.getElementById('prodDetailDesc').value.trim();
const detail_images = detail_images_raw ? detail_images_raw.split(',').map(s => s.trim()).filter(s => s) : [];
if (!category_id) return toast('请选择系统分类', 'warning');
if (!shop_id) return toast('请选择店铺', 'warning');
if (!shop_category_id) return toast('请选择店铺分类', 'warning');
if (!title || !price) return toast('请填写完整信息', 'error');
try {
await apiRequest('/admin/products', {
method: 'POST',
body: JSON.stringify({ game: '暗区突围', title, desc, price, quantity, image, category_id, detail_images, detail_desc, shop_id, shop_category_id })
});
toast('上架成功', 'success');
document.getElementById('prodTitle').value = '';
document.getElementById('prodDesc').value = '';
document.getElementById('prodPrice').value = '';
document.getElementById('prodImageUrl').value = '';
document.getElementById('prodImagePreview').style.display = 'none';
document.getElementById('prodDetailImages').value = '';
document.getElementById('prodDetailDesc').value = '';
renderProductsList();
renderHomePage();
renderCategoryPage();
if (currentSubPage === 'products') renderSubProducts();
} catch (err) { toast(err.message, 'error'); }
}
window.confirmUnshelf = function(productId) {
confirmAction('确认下架', '确认下架此商品?', '确认下架', `doUnshelf('${productId}')`);
};
async function doUnshelf(productId) {
try {
await apiRequest('/admin/products/' + productId + '/unshelf', { method: 'PUT' });
toast('已下架', 'success');
renderProductsList();
renderHomePage();
renderCategoryPage();
if (currentSubPage === 'products') renderSubProducts();
} catch (err) { toast(err.message, 'error'); }
}
window.confirmReshelf = function(productId) {
confirmAction('确认重新上架', '确认重新上架此商品?', '确认上架', `doReshelf('${productId}')`);
};
async function doReshelf(productId) {
try {
await apiRequest('/admin/products/' + productId + '/reshelf', { method: 'PUT' });
toast('已重新上架', 'success');
renderProductsList();
renderHomePage();
renderCategoryPage();
if (currentSubPage === 'products') renderSubProducts();
} catch (err) { toast(err.message, 'error'); }
}
window.confirmDeleteProduct = function(productId) {
confirmAction('确认删除', '⚠️ 确认永久删除此商品?', '确认删除', `doDeleteProduct('${productId}')`);
};
async function doDeleteProduct(productId) {
try {
await apiRequest('/admin/products/' + productId, { method: 'DELETE' });
toast('已删除', 'success');
renderProductsList();
renderHomePage();
renderCategoryPage();
if (currentSubPage === 'products') renderSubProducts();
} catch (err) { toast(err.message, 'error'); }
}
window.openEditProduct = function(productId) {
toast('编辑商品功能开发中,请使用后台管理', 'warning');
};
// ============================================================
// 子页面 - 用户管理(修复加载失败)
// ============================================================
async function renderSubUsers() {
const container = document.getElementById('subUsersContent');
if (!container) return;
try {
const users = await apiRequest('/admin/users');
let html = `
`;
container.innerHTML = html;
await renderUsersListSub();
await populateGiftUsersSub();
} catch (err) {
console.error(err);
container.innerHTML = '加载失败: ' + err.message + '
';
}
}
async function renderUsersListSub() {
try {
const search = document.getElementById('searchUserSub')?.value.toLowerCase() || '';
const users = await apiRequest('/admin/users');
let filtered = users;
if (userFilterSub === 'boss') {
filtered = users.filter(u => u.role === 'boss');
} else if (userFilterSub === 'handler') {
filtered = users.filter(u => u.role === 'handler');
} else if (userFilterSub === 'dispatcher') {
filtered = users.filter(u => u.role === 'dispatcher');
} else if (userFilterSub === 'service') {
filtered = users.filter(u => u.role === 'service');
} else if (userFilterSub === 'pending') {
filtered = users.filter(u => u.status === 'pending' && (u.role === 'handler' || u.role === 'dispatcher' || u.role === 'service'));
}
if (search) {
filtered = filtered.filter(u => u.username.toLowerCase().includes(search));
}
const container = document.getElementById('usersListSub');
if (!container) return;
if (filtered.length === 0) {
container.innerHTML = '';
return;
}
let html = '| 用户名 | 角色 | 红钻 | 状态 | 操作 |
';
for (const u of filtered) {
let roleText = u.role === 'boss' ? '老板' : u.role === 'handler' ? (u.status === 'pending' ? '待审核打手' : '打手') : u.role === 'dispatcher' ? (u.status === 'pending' ? '待审核派单' : '派单员') : u.role === 'service' ? (u.status === 'pending' ? '待审核客服' : '客服') : '管理员';
let statusText2 = u.status === 'active' ? '正常' : u.status === 'pending' ? '待审核' : '封禁';
let statusCls = u.status === 'active' ? 'status-onsale' : u.status === 'pending' ? 'status-pending' : 'status-canceled';
let actions = '';
if (u.role !== 'admin') {
if ((u.role === 'handler' || u.role === 'dispatcher' || u.role === 'service') && u.status === 'pending') {
actions += ``;
}
actions += ``;
actions += ``;
actions += ``;
actions += ``;
}
html += `| ${u.username} | ${roleText} | ${u.diamond||0} | ${statusText2} | ${actions} |
`;
}
html += '
';
container.innerHTML = html;
updateBadges();
} catch (err) {
console.error(err);
const container = document.getElementById('usersListSub');
if (container) {
container.innerHTML = '加载失败: ' + err.message + '
';
}
}
}
function setUserFilterSub(filter) {
userFilterSub = filter;
document.querySelectorAll('.user-filter button').forEach(b => b.classList.remove('active'));
document.querySelector(`.user-filter button[data-filter="${filter}"]`)?.classList.add('active');
renderUsersListSub();
}
async function populateGiftUsersSub() {
try {
const users = await apiRequest('/admin/users');
const sel = document.getElementById('giftUserSub');
if (!sel) return;
sel.innerHTML = '';
users.forEach(u => {
sel.innerHTML += ``;
});
} catch (err) { console.error(err); }
}
async function sendGiftSub() {
const targetUserId = document.getElementById('giftUserSub').value;
const amount = parseInt(document.getElementById('giftAmountSub').value);
if (!targetUserId || !amount) return toast('请选择用户并输入数量', 'error');
try {
await apiRequest('/admin/gift', { method: 'POST', body: JSON.stringify({ targetUserId, amount }) });
toast('赠送成功', 'success');
document.getElementById('giftAmountSub').value = '';
renderUsersListSub();
renderHomePage();
updateHeaderDiamond();
if (currentSubPage === 'users') renderSubUsers();
} catch (err) { toast(err.message, 'error'); }
}
window.approveHandler = function(userId) {
confirmAction('审核通过', '确认通过此账号审核?', '确认通过', `doApproveHandler('${userId}')`);
};
async function doApproveHandler(userId) {
try {
await apiRequest('/admin/users/' + userId + '/approve', { method: 'PUT' });
toast('✅ 审核通过', 'success');
renderUsersListSub();
updateBadges();
if (currentSubPage === 'users') renderSubUsers();
} catch (err) { toast(err.message, 'error'); }
}
window.toggleUserBan = function(userId) {
confirmAction('确认操作', '确认更改此用户状态?', '确认', `doToggleUserBan('${userId}')`);
};
async function doToggleUserBan(userId) {
try {
await apiRequest('/admin/users/' + userId + '/ban', { method: 'PUT' });
toast('用户状态已更新', 'success');
renderUsersListSub();
updateBadges();
if (currentSubPage === 'users') renderSubUsers();
} catch (err) { toast(err.message, 'error'); }
}
window.resetUserPassword = function(userId) {
confirmAction('重置密码', '确认将用户密码重置为 123456?', '确认重置', `doResetPassword('${userId}')`);
};
async function doResetPassword(userId) {
try {
await apiRequest('/admin/users/' + userId + '/reset-password', { method: 'PUT' });
toast('密码已重置为 123456', 'success');
} catch (err) { toast(err.message, 'error'); }
}
window.changeUsername = function(userId, currentName) {
showCustomModal(`
修改用户名
当前用户名:${currentName}
`);
};
async function doChangeUsername(userId) {
const newUsername = document.getElementById('newUsernameInput').value.trim();
if (!newUsername) return toast('请输入新用户名', 'warning');
try {
await apiRequest('/admin/users/' + userId + '/username', { method: 'PUT', body: JSON.stringify({ username: newUsername }) });
closeCustomModal();
toast('✅ 用户名已修改', 'success');
renderUsersListSub();
if (currentSubPage === 'users') renderSubUsers();
} catch (err) { toast(err.message, 'error'); }
}
window.deleteUser = function(userId) {
confirmAction('确认删除', '⚠️ 确认永久删除此用户?此操作不可恢复!', '确认删除', `doDeleteUser('${userId}')`);
};
async function doDeleteUser(userId) {
try {
await apiRequest('/admin/users/' + userId, { method: 'DELETE' });
toast('已删除', 'success');
renderUsersListSub();
if (currentSubPage === 'users') renderSubUsers();
} catch (err) { toast(err.message, 'error'); }
}
// ============================================================
// 子页面 - 店铺管理
// ============================================================
async function renderSubShops() {
const container = document.getElementById('subShopsContent');
if (!container) return;
try {
const shops = await apiRequest('/shops') || [];
const categories = await apiRequest('/categories');
const mainCats = categories.filter(c => !c.parent_id);
let html = `
🏷️ 添加店铺分类
`;
container.innerHTML = html;
const shopList = document.getElementById('shopList');
if (shops.length === 0) {
shopList.innerHTML = '';
} else {
let shopHtml = '| 名称 | 状态 | 标签 | 分类 | 操作 |
';
for (const s of shops) {
const statusText = s.status === 'active' ? '营业中' : '已关闭';
const statusCls = s.status === 'active' ? 'status-onsale' : 'status-canceled';
let tags = [];
if (s.is_self) tags.push('🏆自营');
if (s.is_recommend) tags.push('🔥推荐');
if (s.is_followed) tags.push('⭐关注');
const tagHtml = tags.length > 0 ? tags.join(' ') : '普通';
const catName = mainCats.find(c => c.id === s.category_id)?.name || '未分类';
shopHtml += `
| ${s.name} |
${statusText} |
${tagHtml} |
${catName} |
|
`;
}
shopHtml += '
';
shopList.innerHTML = shopHtml;
}
} catch (err) {
console.error(err);
container.innerHTML = '加载失败: ' + err.message + '
';
}
}
async function createShop() {
const name = document.getElementById('shopName').value.trim();
const description = document.getElementById('shopDesc').value.trim();
const logo = document.getElementById('shopLogo').value.trim();
const banner = document.getElementById('shopBanner').value.trim();
const category_id = document.getElementById('shopCategory').value || null;
const is_self = document.getElementById('shopIsSelf').checked;
const is_recommend = document.getElementById('shopIsRecommend').checked;
if (!name) return toast('请输入店铺名称', 'warning');
if (!category_id) return toast('请选择主分类', 'warning');
try {
await apiRequest('/shops', {
method: 'POST',
body: JSON.stringify({ name, description, logo, banner, category_id, is_self, is_recommend })
});
toast('店铺创建成功', 'success');
document.getElementById('shopName').value = '';
document.getElementById('shopDesc').value = '';
document.getElementById('shopLogo').value = '';
document.getElementById('shopBanner').value = '';
document.getElementById('shopIsSelf').checked = false;
document.getElementById('shopIsRecommend').checked = true;
toggleInlineModal('addShop');
renderSubShops();
renderHomePage();
} catch (err) {
toast(err.message, 'error');
}
}
async function createShopCategory() {
const shop_id = document.getElementById('shopCategorySelect').value;
const name = document.getElementById('shopCategoryName').value.trim();
if (!shop_id) return toast('请选择店铺', 'warning');
if (!name) return toast('请输入分类名称', 'warning');
try {
await apiRequest('/shop-categories', {
method: 'POST',
body: JSON.stringify({ shop_id, name })
});
toast('店铺分类添加成功', 'success');
document.getElementById('shopCategoryName').value = '';
toggleInlineModal('addShopCategory');
renderSubShops();
} catch (err) {
toast(err.message, 'error');
}
}
async function editShop(shopId) {
try {
const shop = await apiRequest('/shops/' + shopId);
const categories = await apiRequest('/categories');
const mainCats = categories.filter(c => !c.parent_id);
let catOptions = '';
mainCats.forEach(c => {
catOptions += ``;
});
showCustomModal(`
✏️ 编辑店铺
`);
document.getElementById('customModal').classList.add('active');
} catch (err) {
toast(err.message, 'error');
}
}
async function doEditShop(shopId) {
const name = document.getElementById('editShopName').value.trim();
const description = document.getElementById('editShopDesc').value.trim();
const logo = document.getElementById('editShopLogo').value.trim();
const banner = document.getElementById('editShopBanner').value.trim();
const category_id = document.getElementById('editShopCategory').value || null;
const is_self = document.getElementById('editShopIsSelf').checked;
const is_recommend = document.getElementById('editShopIsRecommend').checked;
if (!name) return toast('请输入店铺名称', 'warning');
try {
await apiRequest('/shops/' + shopId, {
method: 'PUT',
body: JSON.stringify({ name, description, logo, banner, category_id, is_self, is_recommend })
});
closeCustomModal();
toast('店铺已更新', 'success');
renderSubShops();
renderHomePage();
} catch (err) {
toast(err.message, 'error');
}
}
async function toggleShop(shopId) {
try {
await apiRequest('/shops/' + shopId + '/toggle', { method: 'PUT' });
toast('店铺状态已更新', 'success');
renderSubShops();
renderHomePage();
} catch (err) {
toast(err.message, 'error');
}
}
window.confirmDeleteShop = function(shopId) {
confirmAction('确认删除', '确认删除此店铺?', '确认删除', `doDeleteShop('${shopId}')`);
};
async function doDeleteShop(shopId) {
try {
await apiRequest('/shops/' + shopId, { method: 'DELETE' });
toast('已删除', 'success');
renderSubShops();
renderHomePage();
} catch (err) {
toast(err.message, 'error');
}
}
// ============================================================
// 子页面 - 充值管理
// ============================================================
async function renderSubRecharges() {
const container = document.getElementById('subRechargesContent');
if (!container) return;
try {
const recharges = await apiRequest('/admin/recharges');
let html = `
`;
container.innerHTML = html;
const listContainer = document.getElementById('rechargeListSub');
if (recharges.length === 0) {
listContainer.innerHTML = '';
} else {
let listHtml = '| 用户 | 金额 | 红钻 | 状态 | 操作 |
';
for (const r of recharges) {
const username = r.username || r.user_id || '未知用户';
const statusText2 = r.status === 'pending' ? '待审核' : r.status === 'approved' ? '已通过' : '已拒绝';
const statusCls = r.status === 'pending' ? 'status-pending' : r.status === 'approved' ? 'status-onsale' : 'status-canceled';
let actions = '';
if (r.status === 'pending') {
actions += ``;
actions += ``;
}
actions += ``;
listHtml += `| ${username} | ¥${r.amount} | ${r.diamond} | ${statusText2} | ${actions} |
`;
}
listHtml += '
';
listContainer.innerHTML = listHtml;
}
} catch (err) {
console.error(err);
container.innerHTML = '加载失败: ' + err.message + '
';
}
}
window.confirmApproveRecharge = function(rechargeId) {
confirmAction('确认通过充值', '确认通过此充值申请?红钻将直接到账。', '确认通过', `doApproveRecharge('${rechargeId}')`);
};
async function doApproveRecharge(rechargeId) {
try {
await apiRequest('/admin/recharges/' + rechargeId + '/approve', { method: 'PUT' });
toast('✅ 充值已通过,红钻已到账', 'success');
renderSubRecharges();
renderHomePage();
updateHeaderDiamond();
updateBadges();
} catch (err) { toast(err.message, 'error'); }
}
window.confirmRejectRecharge = function(rechargeId) {
confirmAction('确认拒绝充值', '确认拒绝此充值申请?', '确认拒绝', `doRejectRecharge('${rechargeId}')`);
};
async function doRejectRecharge(rechargeId) {
try {
await apiRequest('/admin/recharges/' + rechargeId + '/reject', { method: 'PUT' });
toast('已拒绝', 'warning');
renderSubRecharges();
updateBadges();
} catch (err) { toast(err.message, 'error'); }
}
window.confirmDeleteRecharge = function(rechargeId) {
confirmAction('确认删除', '确认删除此充值申请?', '确认删除', `doDeleteRecharge('${rechargeId}')`);
};
async function doDeleteRecharge(rechargeId) {
try {
await apiRequest('/admin/recharges/' + rechargeId, { method: 'DELETE' });
toast('已删除', 'success');
renderSubRecharges();
updateBadges();
} catch (err) { toast(err.message, 'error'); }
}
// ============================================================
// 子页面 - 公告管理
// ============================================================
async function renderSubAnnounce() {
const container = document.getElementById('subAnnounceContent');
if (!container) return;
try {
const data = await fetch(API_URL + '/announce').then(r => r.json());
let html = `
`;
container.innerHTML = html;
announceImages = data.images || [];
renderAnnounceImagePreviewSub();
document.getElementById('announcePreviewSub').innerHTML = (data.content || '') + (data.images && data.images.length > 0 ? '
' + data.images.map(img => '

').join('') + '
' : '');
document.getElementById('announceEditContentSub').addEventListener('input', function() {
const preview = document.getElementById('announcePreviewSub');
preview.innerHTML = this.value + (announceImages.length > 0 ? '
' + announceImages.map(img => '

').join('') + '
' : '');
});
} catch (err) {
console.error(err);
container.innerHTML = '加载失败: ' + err.message + '
';
}
}
function previewAnnounceImagesSub(event) {
const files = event.target.files;
for (let file of files) {
const reader = new FileReader();
reader.onload = function(e) {
announceImages.push(e.target.result);
renderAnnounceImagePreviewSub();
};
reader.readAsDataURL(file);
}
event.target.value = '';
}
function renderAnnounceImagePreviewSub() {
const container = document.getElementById('announceImagePreviewSub');
if (!container) return;
container.innerHTML = announceImages.map((img, i) =>
`
`
).join('');
}
function removeAnnounceImageSub(index) {
announceImages.splice(index, 1);
renderAnnounceImagePreviewSub();
}
async function saveAnnounceSub() {
const content = document.getElementById('announceEditContentSub').value.trim();
if (!content) return toast('请输入公告内容', 'warning');
try {
await apiRequest('/admin/announce', { method: 'PUT', body: JSON.stringify({ content, images: announceImages }) });
toast('公告已保存', 'success');
renderSubAnnounce();
await loadAnnounceData();
} catch (err) { toast(err.message, 'error'); }
}
// ============================================================
// 子页面 - 提现管理
// ============================================================
async function renderSubWithdrawals() {
const container = document.getElementById('subWithdrawalsContent');
if (!container) return;
try {
const withdrawals = await apiRequest('/admin/withdrawals');
if (withdrawals.length === 0) {
container.innerHTML = '';
return;
}
let html = '| 用户 | 金额 | 状态 | 操作 |
';
for (const w of withdrawals) {
const statusMap = { 'pending': '待处理', 'approved': '已通过', 'rejected': '已拒绝' };
const statusCls = w.status === 'pending' ? 'status-pending' : w.status === 'approved' ? 'status-onsale' : 'status-canceled';
let actions = '';
if (w.status === 'pending') {
actions += ``;
actions += ``;
}
actions += ``;
html += `
| ${w.username || w.user_id} |
${w.amount} 红钻 |
${statusMap[w.status] || w.status} |
${actions} |
`;
}
html += '
';
container.innerHTML = html;
} catch (err) {
console.error(err);
container.innerHTML = '加载失败: ' + err.message + '
';
}
}
window.approveWithdraw = function(withdrawId) {
confirmAction('确认通过', '确认通过此提现申请?红钻将扣除。', '确认通过', `doApproveWithdraw('${withdrawId}')`);
};
async function doApproveWithdraw(withdrawId) {
try {
await apiRequest('/admin/withdrawals/' + withdrawId + '/approve', { method: 'PUT' });
toast('提现已通过', 'success');
renderSubWithdrawals();
updateHeaderDiamond();
} catch (err) { toast(err.message, 'error'); }
}
window.rejectWithdraw = function(withdrawId) {
const reason = prompt('请输入拒绝原因:');
if (reason === null) return;
confirmAction('确认拒绝', '确认拒绝此提现申请?', '确认拒绝', `doRejectWithdraw('${withdrawId}', '${reason || '无原因'}')`);
};
async function doRejectWithdraw(withdrawId, reason) {
try {
await apiRequest('/admin/withdrawals/' + withdrawId + '/reject', {
method: 'PUT',
body: JSON.stringify({ reason })
});
toast('已拒绝', 'warning');
renderSubWithdrawals();
updateHeaderDiamond();
} catch (err) { toast(err.message, 'error'); }
}
window.deleteWithdraw = function(withdrawId) {
confirmAction('确认删除', '确认删除此提现记录?', '确认删除', `doDeleteWithdraw('${withdrawId}')`);
};
async function doDeleteWithdraw(withdrawId) {
try {
await apiRequest('/admin/withdrawals/' + withdrawId, { method: 'DELETE' });
toast('已删除', 'success');
renderSubWithdrawals();
} catch (err) { toast(err.message, 'error'); }
}
// ============================================================
// 子页面 - 账户设置
// ============================================================
function renderSubAccount() {
const container = document.getElementById('subAccountContent');
if (!container) return;
container.innerHTML = `
个人信息
用户名${currentUser?.username || '-'}
用户ID${currentUser?.id || '-'}
角色${currentUser?.role || '-'}
状态${currentUser?.status || '-'}
红钻余额${currentUser?.diamond || 0}
`;
}
function showChangeName() {
showCustomModal(`
修改昵称
当前昵称:${currentUser?.username}
`);
}
async function doChangeName() {
const newName = document.getElementById('newNameInput').value.trim();
if (!newName) return toast('请输入新昵称', 'warning');
try {
await apiRequest('/user/name', {
method: 'PUT',
body: JSON.stringify({ username: newName })
});
closeCustomModal();
toast('✅ 昵称已修改', 'success');
currentUser.username = newName;
renderMyPage();
updateRoleBasedUI();
} catch (err) {
toast(err.message, 'error');
}
}
function showChangeBanner() {
showCustomModal(`
设置背景墙
输入图片URL设置个人主页背景墙
`);
document.getElementById('bannerUrlInput').addEventListener('input', function() {
const img = document.getElementById('bannerPreview');
if (this.value) {
img.src = this.value;
img.style.display = 'block';
img.onerror = function() { this.style.display = 'none'; };
} else {
img.style.display = 'none';
}
});
}
async function doChangeBanner() {
const url = document.getElementById('bannerUrlInput').value.trim();
if (!url) return toast('请输入图片URL', 'warning');
try {
await apiRequest('/user/banner', {
method: 'PUT',
body: JSON.stringify({ banner: url })
});
closeCustomModal();
toast('✅ 背景墙已更新', 'success');
renderMyPage();
} catch (err) {
toast(err.message, 'error');
}
}
async function changeUserId() {
const newId = document.getElementById('newUserIdInput').value.trim();
if (!newId) return toast('请输入新ID', 'warning');
if (!/^\d{6,}$/.test(newId)) return toast('ID必须为6位以上数字', 'warning');
confirmAction('确认修改ID', `确认将用户ID修改为 ${newId}?此操作不可回退!`, '确认修改', `doChangeUserId('${newId}')`);
}
async function doChangeUserId(newId) {
try {
await apiRequest('/admin/user-id', {
method: 'PUT',
body: JSON.stringify({ targetUserId: currentUser.id, newId: newId })
});
toast('✅ ID已修改,请重新登录', 'success');
setTimeout(() => {
logout();
}, 1500);
} catch (err) {
toast(err.message, 'error');
}
}
function updateRoleBasedUI() {
if (currentUser) {
document.getElementById('authStatusText').textContent = currentUser.username;
}
}
// ============================================================
// 子页面 - 客服系统
// ============================================================
async function renderSubService() {
const container = document.getElementById('subServiceContent');
if (!container) return;
try {
const recharges = await apiRequest('/service/recharges');
const user = await apiRequest('/me');
let html = `
客服面板
${recharges.filter(r => r.status === 'pending').length}
待审核充值
${recharges.filter(r => r.status === 'approved').length}
已处理
赠送红钻
`;
container.innerHTML = html;
await renderServiceRecharges();
await loadServiceUsers();
await loadServiceContacts();
} catch (err) {
console.error(err);
container.innerHTML = '加载失败: ' + err.message + '
';
}
}
async function renderServiceRecharges() {
try {
const recharges = await apiRequest('/service/recharges');
const container = document.getElementById('serviceRechargeList');
if (!container) return;
if (recharges.length === 0) {
container.innerHTML = '';
return;
}
let html = '| 用户 | 金额 | 红钻 | 操作 |
';
for (const r of recharges) {
html += `| ${r.username || r.user_id} | ¥${r.amount} | ${r.diamond} | |
`;
}
html += '
';
container.innerHTML = html;
} catch (err) { console.error(err); }
}
async function serviceApproveRecharge(requestId) {
confirmAction('确认通过', '确认通过此充值申请?将扣除您的红钻。', '确认通过', `doServiceApproveRecharge('${requestId}')`);
}
async function doServiceApproveRecharge(requestId) {
try {
const result = await apiRequest('/service/process', {
method: 'POST',
body: JSON.stringify({ requestId, action: 'approve' })
});
toast(result.message || '✅ 充值已处理', 'success');
renderSubService();
renderHomePage();
updateHeaderDiamond();
updateBadges();
} catch (err) { toast(err.message, 'error'); }
}
async function serviceRejectRecharge(requestId) {
const reason = prompt('请输入拒绝原因:');
if (reason === null) return;
try {
const result = await apiRequest('/service/process', {
method: 'POST',
body: JSON.stringify({ requestId, action: 'reject', rejectReason: reason })
});
toast('已拒绝', 'warning');
renderSubService();
} catch (err) { toast(err.message, 'error'); }
}
async function loadServiceUsers() {
try {
const users = await apiRequest('/service/users');
const sel = document.getElementById('serviceGiftUser');
if (!sel) return;
sel.innerHTML = '';
users.forEach(u => {
sel.innerHTML += ``;
});
} catch (err) { console.error(err); }
}
async function serviceSendGift() {
const targetUserId = document.getElementById('serviceGiftUser').value;
const amount = parseInt(document.getElementById('serviceGiftAmount').value);
if (!targetUserId) return toast('请选择用户', 'warning');
if (!amount || amount < 1) return toast('请输入有效数量', 'warning');
confirmAction('确认赠送', `确认赠送 ${amount} 红钻?将扣除您的红钻。`, '确认赠送', `doServiceSendGift('${targetUserId}', ${amount})`);
}
async function doServiceSendGift(targetUserId, amount) {
try {
const result = await apiRequest('/service/gift', {
method: 'POST',
body: JSON.stringify({ targetUserId, amount })
});
toast(result.message || '✅ 赠送成功', 'success');
document.getElementById('serviceGiftAmount').value = '';
renderSubService();
renderHomePage();
updateHeaderDiamond();
} catch (err) { toast(err.message, 'error'); }
}
async function loadServiceContacts() {
try {
const contacts = await apiRequest('/messages/contacts');
const container = document.getElementById('serviceContacts');
if (!container) return;
if (contacts.length === 0) {
container.innerHTML = '';
return;
}
let html = '';
contacts.forEach(c => {
const unreadBadge = c.unread_count > 0 ? `${c.unread_count}` : '';
html += ``;
});
container.innerHTML = html;
} catch (err) { console.error(err); }
}
// ============================================================
// 子页面 - 派单系统
// ============================================================
async function renderSubDispatcher() {
const container = document.getElementById('subDispatcherContent');
if (!container) return;
try {
const stats = await apiRequest('/dispatcher/stats');
const orders = await apiRequest('/dispatcher/orders');
let html = `
派单仪表盘
${stats.completed || 0}
已完成
`;
container.innerHTML = html;
document.getElementById('dispatcherOrderCountSub').textContent = `(${orders.length})`;
const listContainer = document.getElementById('dispatcherOrdersListSub');
if (orders.length === 0) {
listContainer.innerHTML = '';
} else {
let listHtml = '| 订单号 | 标题 | 金额 | 状态 | 操作 |
';
for (const o of orders) {
let actions = '';
if (o.status === 'pending' || o.status === 'ongoing') {
actions += ``;
}
if (o.status === 'ongoing' || o.status === 'pending') {
actions += ``;
}
actions += ``;
listHtml += `| ${o.id} | ${o.title} | ${o.price} 红钻 | ${statusText(o.status)} | ${actions} |
`;
}
listHtml += '
';
listContainer.innerHTML = listHtml;
}
} catch (err) {
console.error(err);
container.innerHTML = '加载失败: ' + err.message + '
';
}
}
async function dispatcherDirectPublishSub() {
const game = document.getElementById('dispatcherDirectGameSub').value.trim() || '暗区突围';
const title = document.getElementById('dispatcherDirectTitleSub').value.trim();
const desc = document.getElementById('dispatcherDirectDescSub').value.trim();
const price = parseFloat(document.getElementById('dispatcherDirectPriceSub').value);
if (!title || !price) return toast('请填写完整信息', 'error');
if (price < 1) return toast('价格至少为1红钻', 'error');
try {
const result = await apiRequest('/dispatcher/publish', {
method: 'POST',
body: JSON.stringify({ game, title, desc, price, assignedHandlerId: null })
});
toast(result.message || '✅ 订单已发布', 'success');
document.getElementById('dispatcherDirectTitleSub').value = '';
document.getElementById('dispatcherDirectDescSub').value = '';
document.getElementById('dispatcherDirectPriceSub').value = '';
renderSubDispatcher();
renderOrders();
updateHeaderDiamond();
} catch (err) { toast(err.message, 'error'); }
}
window.dispatcherCancelOrder = function(orderId) {
confirmAction('确认撤销', '确认撤销此订单?', '确认撤销', `doDispatcherCancelOrder('${orderId}')`);
};
async function doDispatcherCancelOrder(orderId) {
try {
await apiRequest('/orders/' + orderId + '/cancel', { method: 'PUT' });
toast('订单已撤销', 'success');
renderSubDispatcher();
renderOrders();
} catch (err) { toast(err.message, 'error'); }
}
window.dispatcherConfirmOrder = function(orderId) {
confirmAction('确认完成', '确认此订单已完成?', '确认完成', `doDispatcherConfirmOrder('${orderId}')`);
};
async function doDispatcherConfirmOrder(orderId) {
try {
await apiRequest('/orders/' + orderId + '/dispatcher-confirm', { method: 'PUT' });
toast('订单已完成', 'success');
renderSubDispatcher();
renderOrders();
updateHeaderDiamond();
} catch (err) { toast(err.message, 'error'); }
}
// ============================================================
// 子页面 - 分类管理
// ============================================================
async function renderSubCategories() {
const container = document.getElementById('subCategoriesContent');
if (!container) return;
try {
const categories = await apiRequest('/categories');
const mainCats = categories.filter(c => !c.parent_id);
const subCats = categories.filter(c => c.parent_id);
let html = `
🏷️ 创建子分类
`;
container.innerHTML = html;
const listContainer = document.getElementById('categoriesList');
if (categories.length === 0) {
listContainer.innerHTML = '';
} else {
let listHtml = '';
listContainer.innerHTML = listHtml;
}
} catch (err) {
console.error(err);
container.innerHTML = '加载失败: ' + err.message + '
';
}
}
async function createCategory() {
const name = document.getElementById('categoryName').value.trim();
const image = document.getElementById('categoryImage').value.trim();
const sort_order = parseInt(document.getElementById('categorySortOrder').value) || 0;
if (!name) return toast('请输入分类名称', 'warning');
try {
await apiRequest('/admin/categories', {
method: 'POST',
body: JSON.stringify({ name, image, sort_order, parent_id: null })
});
toast('分类创建成功', 'success');
document.getElementById('categoryName').value = '';
document.getElementById('categoryImage').value = '';
document.getElementById('categorySortOrder').value = '0';
toggleInlineModal('addCategory');
renderSubCategories();
loadCategoryNav();
} catch (err) {
toast(err.message, 'error');
}
}
async function createSubCategory() {
const parent_id = document.getElementById('subCategoryParent').value;
const name = document.getElementById('subCategoryName').value.trim();
if (!parent_id) return toast('请选择主分类', 'warning');
if (!name) return toast('请输入子分类名称', 'warning');
try {
await apiRequest('/admin/categories', {
method: 'POST',
body: JSON.stringify({ name, parent_id, sort_order: 0 })
});
toast('子分类创建成功', 'success');
document.getElementById('subCategoryName').value = '';
toggleInlineModal('addSubCategory');
renderSubCategories();
loadCategoryNav();
} catch (err) {
toast(err.message, 'error');
}
}
async function editCategory(categoryId) {
try {
const categories = await apiRequest('/categories');
const cat = categories.find(c => c.id === categoryId);
if (!cat) return toast('分类不存在', 'error');
showCustomModal(`
编辑分类
`);
document.getElementById('customModal').classList.add('active');
} catch (err) {
toast(err.message, 'error');
}
}
async function doEditCategory(categoryId) {
const name = document.getElementById('editCategoryName').value.trim();
const image = document.getElementById('editCategoryImage').value.trim();
const sort_order = parseInt(document.getElementById('editCategorySortOrder').value) || 0;
if (!name) return toast('请输入分类名称', 'error');
try {
await apiRequest('/admin/categories/' + categoryId + '/edit', {
method: 'PUT',
body: JSON.stringify({ name, image, sort_order })
});
closeCustomModal();
toast('分类已更新', 'success');
renderSubCategories();
loadCategoryNav();
} catch (err) {
toast(err.message, 'error');
}
}
window.confirmDeleteCategory = function(categoryId) {
confirmAction('确认删除', '确认删除此分类?', '确认删除', `doDeleteCategory('${categoryId}')`);
};
async function doDeleteCategory(categoryId) {
try {
await apiRequest('/admin/categories/' + categoryId, { method: 'DELETE' });
toast('已删除', 'success');
renderSubCategories();
loadCategoryNav();
} catch (err) {
toast(err.message, 'error');
}
}
async function updateCategorySort(categoryId, sortOrder) {
try {
await apiRequest('/admin/categories/' + categoryId + '/edit', {
method: 'PUT',
body: JSON.stringify({ sort_order: parseInt(sortOrder) || 0 })
});
toast('排序已更新', 'success');
renderSubCategories();
loadCategoryNav();
} catch (err) {
toast(err.message, 'error');
}
}
async function loadCategoryNav() {
try {
const categories = await apiRequest('/categories');
const container = document.getElementById('categoryButtons2');
if (!container) return;
const mainCategories = categories.filter(c => !c.parent_id).sort((a, b) => (Number(a.sort_order) || 0) - (Number(b.sort_order) || 0));
container.innerHTML = '';
mainCategories.forEach(c => {
const btn = document.createElement('button');
btn.className = 'category-btn';
btn.dataset.category = c.id;
btn.textContent = c.image ? c.image + ' ' + c.name : c.name;
btn.onclick = function() { filterProductsByCategory(c.id); };
container.appendChild(btn);
});
} catch (err) {
console.error('加载分类导航失败', err);
}
}
// ============================================================
// 子页面 - 广告管理
// ============================================================
async function renderSubBanners() {
const container = document.getElementById('subBannersContent');
if (!container) return;
try {
const banners = await apiRequest('/banners') || [];
let html = `
`;
container.innerHTML = html;
const listContainer = document.getElementById('bannerList');
if (banners.length === 0) {
listContainer.innerHTML = '';
} else {
let listHtml = '| 图片 | 排序 | 操作 |
';
for (const b of banners) {
listHtml += `
 |
${b.sort_order || 0} |
|
`;
}
listHtml += '
';
listContainer.innerHTML = listHtml;
}
} catch (err) {
console.error(err);
container.innerHTML = '加载失败: ' + err.message + '
';
}
}
async function createBanner() {
const image_url = document.getElementById('bannerImageUrl').value.trim();
const link = document.getElementById('bannerLink').value.trim();
const sort_order = parseInt(document.getElementById('bannerSortOrder').value) || 0;
if (!image_url) return toast('请输入图片URL', 'warning');
try {
const result = await apiRequest('/admin/banners', {
method: 'POST',
body: JSON.stringify({ image_url, link, sort_order })
});
toast('广告添加成功', 'success');
document.getElementById('bannerImageUrl').value = '';
document.getElementById('bannerLink').value = '';
document.getElementById('bannerSortOrder').value = '0';
toggleInlineModal('addBanner');
renderSubBanners();
await loadBannersFromAPI();
} catch (err) {
toast(err.message, 'error');
}
}
window.confirmDeleteBanner = function(bannerId) {
confirmAction('确认删除', '确认删除此广告?', '确认删除', `doDeleteBanner('${bannerId}')`);
};
async function doDeleteBanner(bannerId) {
try {
await apiRequest('/admin/banners/' + bannerId, { method: 'DELETE' });
toast('已删除', 'success');
renderSubBanners();
await loadBannersFromAPI();
} catch (err) {
toast(err.message, 'error');
}
}
// ============================================================
// 子页面 - 图标管理
// ============================================================
async function renderSubIcons() {
const container = document.getElementById('subIconsContent');
if (!container) return;
try {
const icons = await apiRequest('/icons') || [];
const iconKeys = [
{ key: 'shop_default', label: '店铺默认图标' },
{ key: 'product_default', label: '商品默认图标' },
{ key: 'banner_default', label: '广告默认图标' },
{ key: 'avatar_default', label: '默认头像' },
{ key: 'logo', label: '网站Logo' }
];
let html = `
🎨 图标自定义
上传图片URL自定义网站图标,留空则使用默认图标
`;
container.innerHTML = html;
const listContainer = document.getElementById('iconList');
let listHtml = '';
listContainer.innerHTML = listHtml;
} catch (err) {
console.error(err);
container.innerHTML = '加载失败: ' + err.message + '
';
}
}
async function setIcon(key) {
const image_url = document.getElementById('iconInput_' + key).value.trim();
if (!image_url) return toast('请输入图片URL', 'warning');
try {
await apiRequest('/admin/icons', {
method: 'POST',
body: JSON.stringify({ key, image_url })
});
toast('图标已更新', 'success');
renderSubIcons();
applyCustomIcons();
} catch (err) {
toast(err.message, 'error');
}
}
async function deleteIcon(key) {
confirmAction('确认清除', '确认清除此自定义图标?', '确认清除', `doDeleteIcon('${key}')`);
}
async function doDeleteIcon(key) {
try {
await apiRequest('/admin/icons/' + key, { method: 'DELETE' });
toast('图标已清除', 'success');
renderSubIcons();
applyCustomIcons();
} catch (err) {
toast(err.message, 'error');
}
}
function applyCustomIcons() {
apiRequest('/icons').then(icons => {
icons.forEach(icon => {
if (icon.key === 'logo') {
const logoEl = document.getElementById('brandIcon');
if (logoEl && icon.image_url) {
logoEl.style.background = 'none';
logoEl.innerHTML = `
`;
}
}
});
}).catch(err => console.error('加载自定义图标失败', err));
}
// ============================================================
// 消息系统
// ============================================================
async function loadContacts() {
try {
const search = document.getElementById('searchContact')?.value.toLowerCase() || '';
const contacts = await apiRequest('/messages/contacts');
const container = document.getElementById('contactList');
if (!container) return;
let supportContacts = [];
try {
supportContacts = await getSupportContacts();
} catch (e) {
console.warn('获取支持联系人失败:', e);
supportContacts = [];
}
const isService = currentUser && (currentUser.role === 'service' || currentUser.role === 'admin');
let filtered = contacts || [];
if (search) {
filtered = filtered.filter(c => (c.username && c.username.toLowerCase().includes(search)) || (c.id && c.id.toLowerCase().includes(search)));
}
const totalUnread = filtered.reduce((sum, c) => sum + (c.unread_count || 0), 0);
const totalEl = document.getElementById('msgUnreadTotal');
if (totalEl) totalEl.textContent = totalUnread > 0 ? `(${totalUnread}条未读)` : '';
let supportHtml = '';
if (!isService && supportContacts && supportContacts.length > 0) {
const existingContactIds = (contacts || []).map(c => c.id);
const availableSupport = supportContacts.filter(s => !existingContactIds.includes(s.id));
if (availableSupport.length > 0) {
supportHtml = ``;
}
}
const addContactHtml = ``;
if (filtered.length === 0 && !supportHtml) {
container.innerHTML = addContactHtml + `暂无联系人
${isService ? `
` : ''}
`;
return;
}
let html = addContactHtml + supportHtml;
if (isService) {
html += ``;
}
filtered.forEach(c => {
const unreadBadge = c.unread_count > 0 ? `${c.unread_count}` : '';
const roleIcon = c.role === 'admin' ? '🔴' : c.role === 'service' ? '🟢' : '';
const displayName = c.username || c.id || '未知用户';
html += ``;
});
container.innerHTML = html;
} catch (err) {
console.error('加载联系人失败:', err);
const container = document.getElementById('contactList');
if (container) {
container.innerHTML = `加载联系人失败: ${err.message}
`;
}
}
}
async function addContactById() {
const input = document.getElementById('addContactById');
const userId = input.value.trim();
if (!userId) return toast('请输入用户ID', 'warning');
try {
const users = await apiRequest('/admin/users');
const user = users.find(u => u.id === userId);
if (!user) return toast('用户不存在', 'error');
if (user.id === currentUser.id) return toast('不能添加自己', 'warning');
await apiRequest('/messages/send', {
method: 'POST',
body: JSON.stringify({ receiverId: userId, content: '你好,我们开始聊天吧!' })
});
toast('✅ 已添加联系人', 'success');
input.value = '';
loadContacts();
updateBadges();
} catch (err) {
toast(err.message, 'error');
}
}
// ============================================================
// 全屏聊天
// ============================================================
async function openChat(id, username, type = 'contact') {
if (!currentUser) { toast('请先登录', 'warning'); return; }
if (!id) { toast('联系人ID无效', 'error'); return; }
fullscreenContactId = id;
fullscreenChatType = type;
fullscreenOrderId = type === 'order' ? id : null;
const container = document.getElementById('chatFullscreen');
container.classList.add('active');
document.body.style.overflow = 'hidden';
document.getElementById('fullscreenChatName').textContent = username || id;
try {
const users = await apiRequest('/admin/users');
const user = users.find(u => u.id === id);
if (user) {
const roleMap = { 'boss': '老板', 'handler': '打手', 'dispatcher': '派单', 'service': '客服', 'admin': '管理员' };
document.getElementById('fullscreenChatRole').textContent = roleMap[user.role] || '用户';
} else if (type === 'order') {
document.getElementById('fullscreenChatRole').textContent = '📋 订单聊天';
}
} catch (e) {
if (type === 'order') document.getElementById('fullscreenChatRole').textContent = '📋 订单聊天';
}
await loadFullscreenMessages();
}
async function loadFullscreenMessages() {
const body = document.getElementById('fullscreenChatBody');
body.innerHTML = '';
try {
const messages = await apiRequest('/messages/history', {
method: 'POST',
body: JSON.stringify({ contactId: fullscreenContactId })
});
if (messages.length === 0) {
body.innerHTML = '';
} else {
let html = '';
messages.forEach(m => {
const isMe = m.sender_id === currentUser.id;
html += `${m.content}${new Date(m.created_at).toLocaleTimeString()}
`;
});
body.innerHTML = html;
body.scrollTop = body.scrollHeight;
}
updateBadges();
} catch (err) {
console.error('加载消息失败:', err);
body.innerHTML = ``;
}
}
async function sendFullscreenMessage() {
const input = document.getElementById('fullscreenChatInput');
const content = input.value.trim();
if (!content) return toast('请输入消息', 'warning');
if (!fullscreenContactId) return toast('请选择联系人', 'warning');
try {
if (fullscreenChatType === 'order' && fullscreenOrderId) {
await apiRequest('/orders/' + fullscreenOrderId + '/chat', { method: 'POST', body: JSON.stringify({ content }) });
} else {
await apiRequest('/messages/send', { method: 'POST', body: JSON.stringify({ receiverId: fullscreenContactId, content }) });
}
input.value = '';
await loadFullscreenMessages();
} catch (err) {
toast(err.message, 'error');
}
}
function closeChatFullscreen() {
document.getElementById('chatFullscreen').classList.remove('active');
document.body.style.overflow = '';
fullscreenContactId = null;
fullscreenOrderId = null;
fullscreenChatType = 'contact';
loadContacts();
}
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('fullscreenChatInput')?.addEventListener('keydown', function(e) {
if (e.key === 'Enter') {
e.preventDefault();
sendFullscreenMessage();
}
});
});
function showAddContact() {
apiRequest('/admin/users').then(users => {
apiRequest('/messages/contacts').then(contacts => {
const contactIds = contacts.map(c => c.id);
const available = users.filter(u => u.id !== currentUser.id && !contactIds.includes(u.id) && (u.role === 'boss' || u.role === 'handler' || u.role === 'dispatcher'));
if (available.length === 0) {
toast('没有可添加的用户', 'warning');
return;
}
let options = available.map(u => ``).join('');
showCustomModal(`
添加对话
选择要添加的用户:
`);
document.getElementById('customModal').classList.add('active');
});
}).catch(err => toast(err.message, 'error'));
}
async function doAddContact() {
const userId = document.getElementById('addContactSelect').value;
const message = document.getElementById('addContactMessage').value.trim();
if (!userId) return toast('请选择用户', 'warning');
if (!message) return toast('请输入消息', 'warning');
closeCustomModal();
try {
await apiRequest('/messages/send', { method: 'POST', body: JSON.stringify({ receiverId: userId, content: message }) });
toast('✅ 已添加对话', 'success');
loadContacts();
updateBadges();
} catch (err) { toast(err.message, 'error'); }
}
// ============================================================
// 红点更新
// ============================================================
async function updateBadges() {
if (!currentUser) return;
try {
const result = await apiRequest('/messages/unread');
const unread = result.unread || 0;
const badge = document.getElementById('msgBadge');
if (badge) {
if (unread > 0) {
badge.style.display = 'inline-block';
badge.textContent = unread > 99 ? '99+' : unread;
} else {
badge.style.display = 'none';
}
}
} catch (err) {
console.error('更新红点失败', err);
}
}
// ============================================================
// 充值功能
// ============================================================
window.openRecharge = function() {
if (!currentUser) { toast('请先登录', 'warning'); return; }
const html = `
充值红钻
1元 = 10红钻
0 红钻
`;
showCustomModal(html);
document.getElementById('customModal').classList.add('active');
document.getElementById('rechargeAmount').addEventListener('input', function() {
const amount = parseFloat(this.value) || 0;
document.getElementById('rechargePreview').textContent = Math.floor(amount * 10) + ' 红钻';
});
};
function setRechargeAmount(amount) {
document.getElementById('rechargeAmount').value = amount;
document.getElementById('rechargePreview').textContent = Math.floor(amount * 10) + ' 红钻';
}
async function submitCustomRecharge() {
const amount = parseFloat(document.getElementById('rechargeAmount').value);
if (!amount || amount < 1) return toast('请输入有效金额', 'warning');
try {
await apiRequest('/recharge/custom', {
method: 'POST',
body: JSON.stringify({ amount })
});
closeCustomModal();
toast('充值申请已提交,请等待客服审核', 'success');
updateBadges();
} catch (err) {
toast(err.message, 'error');
}
}
// ============================================================
// 邮件功能
// ============================================================
window.openMail = function() {
if (!currentUser) { toast('请先登录', 'warning'); return; }
apiRequest('/mails').then(mails => {
let listHtml = mails.length === 0 ? '' :
mails.map(m => `
${m.title}
${m.status==='unread'?'未领取':'已领取'}
${m.content}
${m.create_time}
${m.status === 'unread' && m.diamond > 0 ? `` : ''}
`).join('');
showCustomModal(`
我的邮件
${listHtml}
`);
}).catch(err => toast(err.message, 'error'));
};
window.confirmClaimMail = function(mailId) {
confirmAction('领取红钻', '确认领取此邮件中的红钻?', '确认领取', `doClaimMail('${mailId}')`);
};
async function doClaimMail(mailId) {
try {
await apiRequest('/mails/' + mailId + '/claim', { method: 'PUT' });
toast('领取成功', 'success');
openMail();
renderHomePage();
updateHeaderDiamond();
} catch (err) { toast(err.message, 'error'); }
}
// ============================================================
// 认证相关
// ============================================================
function toggleAuthModal() {
if (currentUser) {
confirmAction('确认退出', '确定要退出登录吗?', '退出', `doLogout()`);
return;
}
showLoginModal();
}
function showLoginModal() {
showCustomModal(`
登录
还没有账号?
`);
document.getElementById('customModal').classList.add('active');
}
async function doLogin() {
const username = document.getElementById('loginUsername').value.trim();
const password = document.getElementById('loginPassword').value.trim();
const errorEl = document.getElementById('loginError');
errorEl.textContent = '';
if (!username || !password) {
errorEl.textContent = '请填写用户名和密码';
return;
}
try {
const data = await apiRequest('/login', { method: 'POST', body: JSON.stringify({ username, password }) });
token = data.token;
localStorage.setItem('token', token);
currentUser = data.user;
closeCustomModal();
afterLogin();
toast('欢迎回来,' + username, 'success');
} catch (err) {
errorEl.textContent = err.message || '登录失败';
}
}
function showRegisterModal() {
showCustomModal(`
注册
已有账号?
`);
document.getElementById('customModal').classList.add('active');
}
async function doRegister() {
const username = document.getElementById('regUsername').value.trim();
const password = document.getElementById('regPassword').value.trim();
const role = document.getElementById('regRole').value;
const errorEl = document.getElementById('regError');
errorEl.textContent = '';
if (!username || !password) {
errorEl.textContent = '请填写用户名和密码';
return;
}
try {
const data = await apiRequest('/register', { method: 'POST', body: JSON.stringify({ username, password, role }) });
if (role === 'handler' || role === 'dispatcher' || role === 'service') {
toast('注册成功,请等待管理员审核', 'success');
} else {
toast('注册成功,请登录', 'success');
}
closeCustomModal();
showLoginModal();
document.getElementById('loginUsername').value = username;
document.getElementById('loginPassword').value = password;
} catch (err) {
errorEl.textContent = err.message || '注册失败';
}
}
function doLogout() {
localStorage.removeItem('token');
token = null;
currentUser = null;
document.getElementById('authStatusText').textContent = '未登录';
updateHeaderDiamond();
if (window._badgeTimer) {
clearInterval(window._badgeTimer);
window._badgeTimer = null;
}
stopBannerAuto();
renderHomePage();
renderMyPage();
closeSubPage();
closeShopDetail();
closeProductDetail();
toast('已退出', 'warning');
renderBottomNav();
}
function logout() {
if (!currentUser) {
toast('请先登录', 'warning');
return;
}
confirmAction('确认退出', '确定要退出登录吗?', '退出', `doLogout()`);
}
// ============================================================
// 认证模块(登录后)
// ============================================================
function afterLogin() {
document.getElementById('authPage').style.display = 'none';
document.getElementById('mainApp').classList.remove('hidden');
document.getElementById('authStatusText').textContent = currentUser.username;
renderBottomNav();
document.querySelectorAll('.view').forEach(v => v.classList.remove('active'));
document.getElementById('view-home').classList.add('active');
document.querySelectorAll('.bottom-nav .nav-item').forEach(n => {
n.classList.toggle('active', n.dataset.target === 'home');
});
renderHomePage();
renderCategoryPage();
renderMyPage();
renderPosts();
loadContacts();
updateHeaderDiamond();
updateBadges();
applyCustomIcons();
setTimeout(() => {
loadAnnounceData().then(() => {
showAnnounceModal();
});
}, 500);
if (window._badgeTimer) clearInterval(window._badgeTimer);
window._badgeTimer = setInterval(updateBadges, 30000);
}
// ============================================================
// 登录/注册页面按钮
// ============================================================
async function doAuthLogin() {
const username = document.getElementById('authUsername').value.trim();
const password = document.getElementById('authPassword').value.trim();
const errorEl = document.getElementById('authError');
errorEl.textContent = '';
if (!username || !password) {
errorEl.textContent = '请填写用户名和密码';
return;
}
try {
const data = await apiRequest('/login', { method: 'POST', body: JSON.stringify({ username, password }) });
token = data.token;
localStorage.setItem('token', token);
currentUser = data.user;
afterLogin();
toast('欢迎回来,' + username, 'success');
} catch (err) {
errorEl.textContent = err.message || '登录失败';
}
}
async function doAuthRegister() {
const username = document.getElementById('authUsername').value.trim();
const password = document.getElementById('authPassword').value.trim();
const roleEl = document.querySelector('input[name="authRole"]:checked');
const role = roleEl ? roleEl.value : 'boss';
const errorEl = document.getElementById('authError');
errorEl.textContent = '';
if (!username || !password) {
errorEl.textContent = '请填写用户名和密码';
return;
}
try {
const data = await apiRequest('/register', { method: 'POST', body: JSON.stringify({ username, password, role }) });
if (role === 'handler' || role === 'dispatcher' || role === 'service') {
toast('注册成功,请等待管理员审核', 'success');
} else {
toast('注册成功,请登录', 'success');
}
document.getElementById('authPassword').value = '';
} catch (err) {
errorEl.textContent = err.message || '注册失败';
}
}
// ============================================================
// 初始化
// ============================================================
async function init() {
document.getElementById('authPage').style.display = 'none';
document.getElementById('mainApp').classList.remove('hidden');
document.getElementById('authStatusText').textContent = '未登录';
document.getElementById('headerDiamond').textContent = '0';
document.getElementById('headerUnreadMail').textContent = '0';
renderBottomNav();
renderHomePage();
renderCategoryPage();
renderMyPage();
renderPosts();
loadContacts();
const savedToken = localStorage.getItem('token');
if (savedToken) {
token = savedToken;
try {
const user = await apiRequest('/me');
currentUser = user;
document.getElementById('authStatusText').textContent = user.username;
afterLogin();
} catch (err) {
localStorage.removeItem('token');
token = null;
currentUser = null;
document.getElementById('authStatusText').textContent = '未登录';
renderBottomNav();
renderHomePage();
renderMyPage();
}
} else {
renderBottomNav();
setTimeout(() => {
loadAnnounceData().then(() => {
showAnnounceModal();
});
}, 500);
}
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/sw.js')
.then(function(registration) {
console.log('✅ Service Worker 注册成功');
})
.catch(function(error) {
console.log('❌ Service Worker 注册失败:', error);
});
});
}
}
// ============================================================
// 启动应用
// ============================================================
document.addEventListener('DOMContentLoaded', function() {
init();
});
// ============================================================
// 暴露全局函数供HTML调用
// ============================================================
window.navigateTo = navigateTo;
window.openSubPage = openSubPage;
window.closeSubPage = closeSubPage;
window.openProductDetail = openProductDetail;
window.closeProductDetail = closeProductDetail;
window.openShopDetail = openShopDetail;
window.closeShopDetail = closeShopDetail;
window.buyFromDetail = buyFromDetail;
window.showBuyWithHandler = showBuyWithHandler;
window.doBuyWithHandler = doBuyWithHandler;
window.filterProductsByCategory = filterProductsByCategory;
window.filterSubCategory2 = filterSubCategory2;
window.filterMyOrders = filterMyOrders;
window.uploadAvatar = uploadAvatar;
window.requestWithdraw = requestWithdraw;
window.openRecharge = openRecharge;
window.openMail = openMail;
window.toggleAuthModal = toggleAuthModal;
window.showLoginModal = showLoginModal;
window.logout = logout;
window.renderPosts = renderPosts;
window.refreshPosts = refreshPosts;
window.showCreatePost = showCreatePost;
window.submitPost = submitPost;
window.likePost = likePost;
window.toggleComments = toggleComments;
window.submitComment = submitComment;
window.deletePost = deletePost;
window.openChat = openChat;
window.closeChatFullscreen = closeChatFullscreen;
window.sendFullscreenMessage = sendFullscreenMessage;
window.loadContacts = loadContacts;
window.addContactById = addContactById;
window.showAddContact = showAddContact;
window.toggleInlineModal = toggleInlineModal;
window.createShop = createShop;
window.createShopCategory = createShopCategory;
window.editShop = editShop;
window.toggleShop = toggleShop;
window.confirmDeleteShop = confirmDeleteShop;
window.shelfProduct = shelfProduct;
window.confirmUnshelf = confirmUnshelf;
window.confirmReshelf = confirmReshelf;
window.confirmDeleteProduct = confirmDeleteProduct;
window.openEditProduct = openEditProduct;
window.approveHandler = approveHandler;
window.toggleUserBan = toggleUserBan;
window.resetUserPassword = resetUserPassword;
window.changeUsername = changeUsername;
window.deleteUser = deleteUser;
window.confirmApproveRecharge = confirmApproveRecharge;
window.confirmRejectRecharge = confirmRejectRecharge;
window.confirmDeleteRecharge = confirmDeleteRecharge;
window.approveWithdraw = approveWithdraw;
window.rejectWithdraw = rejectWithdraw;
window.deleteWithdraw = deleteWithdraw;
window.dispatcherCancelOrder = dispatcherCancelOrder;
window.dispatcherConfirmOrder = dispatcherConfirmOrder;
window.confirmDeleteCategory = confirmDeleteCategory;
window.confirmDeleteBanner = confirmDeleteBanner;
window.setIcon = setIcon;
window.deleteIcon = deleteIcon;
window.confirmClaimMail = confirmClaimMail;
window.confirmTake = confirmTake;
window.confirmSubmitComplete = confirmSubmitComplete;
window.confirmBossComplete = confirmBossComplete;
window.requestRefund = requestRefund;
window.viewOrderDetail = viewOrderDetail;
window.showChangeName = showChangeName;
window.showChangeBanner = showChangeBanner;
window.doAuthLogin = doAuthLogin;
window.doAuthRegister = doAuthRegister;
window.prevBanner = prevBanner;
window.nextBanner = nextBanner;
window.goToBanner = goToBanner;
window.handleProfileClick = handleProfileClick;
window.setRechargeAmount = setRechargeAmount;
window.submitCustomRecharge = submitCustomRecharge;
window.renderSubOrders = renderSubOrders;
window.renderSubProducts = renderSubProducts;
window.renderSubUsers = renderSubUsers;
window.renderSubRecharges = renderSubRecharges;
window.renderSubShops = renderSubShops;
window.renderSubAnnounce = renderSubAnnounce;
window.renderSubWithdrawals = renderSubWithdrawals;
window.renderSubAccount = renderSubAccount;
window.renderSubService = renderSubService;
window.renderSubDispatcher = renderSubDispatcher;
window.renderSubCategories = renderSubCategories;
window.renderSubBanners = renderSubBanners;
window.renderSubIcons = renderSubIcons;
console.log('✅ QW电竞护航平台 v6.0 完整版已加载');
console.log('📌 所有功能已优化完成 - 店铺可进入、帖子可发布、顶部栏已清理');
请登录后评论
`}